Skip to content

Paper 26: async spawn rescue, Paper API build, DummyChunk, and WorldEdit-safe command init#373

Closed
rkfsociety wants to merge 3 commits into
Jikoo:masterfrom
rkfsociety:master
Closed

Paper 26: async spawn rescue, Paper API build, DummyChunk, and WorldEdit-safe command init#373
rkfsociety wants to merge 3 commits into
Jikoo:masterfrom
rkfsociety:master

Conversation

@rkfsociety
Copy link
Copy Markdown

This branch contains two logical changes (two commits).

1) Paper 26 spawn / rescue + build + DummyChunk

  • Replace deprecated PlayerSpawnLocationEvent with AsyncPlayerSpawnLocationEvent in RescueListener.
  • Run world/chunk work on the main thread using BukkitScheduler#callSyncMethod.
  • Feature marker on disk: read via offline player PDC view; write deferred with runTask after the Player exists (same intent as before).
  • Use OfflinePlayer#getRespawnLocation(true) for respawn-based rescue.
  • Compile against io.papermc.paper:paper-api 26.1.2.build.60-stable (the 26.1.2-R0.1-SNAPSHOT coordinate is not on Paper’s Maven).
  • Update DummyChunk for the current Chunk API (getLoadLevel, isGenerated, getStructures, getPlayersSeeingChunk, four-arg getChunkSnapshot, getTileEntities overloads) and fix isLoaded() (chunkX / chunkZ).

2) WorldEdit classpath / load order

  • FlagHandler pulls in WorldEdit types. Creating it from RegioneratorExecutor during onEnable could run before WorldEdit finished enabling and triggered NoClassDefFoundError for com.sk89q.worldedit.session.SessionOwner.
  • Fix: lazy FlagHandler creation on first /regionerator flag or unflag, and add WorldEdit to plugin.yml softdepend.

rkfsociety added 2 commits May 4, 2026 19:26
Replace deprecated PlayerSpawnLocationEvent; run world access on the main
thread via callSyncMethod. Compile against paper-api 26.1.2.build.60-stable.
Update DummyChunk for current Chunk API (load level, structures, tile
entities, four-arg chunk snapshot).
Defer FlagHandler construction until first flag/unflag command so WorldEdit
classes (e.g. SessionOwner) are on the classpath. Add WorldEdit to plugin
softdepend for ordering when Bukkit resolves dependencies.
Copy link
Copy Markdown
Owner

@Jikoo Jikoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re: WorldEdit - WG depends on WE, so this should not be an issue unless you have dependency loops entirely breaking load order. You should probably check your other plugins if you're having problems.
If you are interested in fixing the problems with it, please submit it as a separate PR.

Re: AsyncPlayerSpawnLocationEvent: I'm not interested in dropping Spigot compatibility. I would be fine with a Spigot and Paper module, but I am not interested in an AI PR doing the required modularization because I would probably go insane wasting the time reviewing that much weird code.

In general, please try to actually look at what your AI did.

Comment on lines +57 to +67
FlagHandler local = this.flagHandler;
if (local == null) {
synchronized (this) {
local = this.flagHandler;
if (local == null) {
local = new FlagHandler(this.plugin);
this.flagHandler = local;
}
}
}
return local;
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Locking is not really necessary here. Commands are processed on the main thread. Even if they weren't (i.e. maybe Folia, which also isn't supported because we use the regular Bukkit scheduler), the odds of two players just so happening to execute commands both requiring a flag handler at the same exact time are incredibly small.

I'm way more concerned with the fact that AI thinks using a publicly-accessible instance for a lock is a good idea. Good lord.

Comment on lines +43 to +47
/**
* Lazily created: {@link FlagHandler} touches WorldEdit types. If we construct it from
* {@link Regionerator#onEnable()} before WorldEdit has enabled, {@code SessionOwner} etc. are not
* visible yet and the plugin fails with {@link NoClassDefFoundError}.
*/
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer docs on the method to the field.

* {@link Regionerator#onEnable()} before WorldEdit has enabled, {@code SessionOwner} etc. are not
* visible yet and the plugin fails with {@link NoClassDefFoundError}.
*/
private volatile @Nullable FlagHandler flagHandler;
Copy link
Copy Markdown
Owner

@Jikoo Jikoo May 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Volatile and a lock? Unnecessary, I would drop the keyword.
/e: Ah, it is necessary due to how the AI set it up. Eugh.

Comment on lines -55 to -59
Player player = event.getPlayer();
// Check if the player has logged in since this feature was added.
PersistentDataContainer playerPdc = player.getPersistentDataContainer();
if (!playerPdc.has(loggedInSinceFeature, PersistentDataType.BYTE)) {
playerPdc.set(loggedInSinceFeature, PersistentDataType.BYTE, (byte) 1);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick returns before incurring a scheduler hit should be re-added. PDC logic does not need to wait for main thread.

Chunk chunk = spawnLoc.getChunk();
PersistentDataContainer chunkPdc = chunk.getPersistentDataContainer();
NamespacedKey logoutKey = getLogoutKey(player.getUniqueId());
// If the key is set, the chunk has not been deleted since the player last logged out.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't delete existing comments.

…aper-only API

Restore spigot-api build, revert Chunk API changes, and remove WorldEdit load-order workaround from this PR. Register Paper AsyncPlayerSpawnLocationEvent handler via reflection when available while keeping PlayerSpawnLocationEvent for Spigot.
@Jikoo
Copy link
Copy Markdown
Owner

Jikoo commented May 7, 2026

Look, I'm gonna be honest, there are a lot of things that are slightly wrong and rather weird with these changes, and I don't really feel like wasting my time giving you feedback to feed into an AI when I could just prompt an AI myself and cut out the middleman.
I will treat this as a feature request for support for the AsyncPlayerSpawnLocationEvent, which I will prioritize because I definitely do recommend using Paper.

If you want to PR lazy access for WE, feel free. Like I said before, the risk of concurrency issues are almost nonexistent even if a platform were to implement async command processing, so it really doesn't need to be complex.
I still think you should probably check your plugin load order for softdepend loops, because that can break load order more subtly. I think Paper has pretty good logging for it, but you could also try https://www.spigotmc.org/resources/pluginvisualizer.122356/ to view relations.

@Jikoo Jikoo closed this May 7, 2026
@rkfsociety
Copy link
Copy Markdown
Author

I basically don't understand programming, I just solved this problem with the help of AI, and after a week I had no errors, I decided to share with the developer, if any of this is useful, use it, if not, then so be it.

@Jikoo
Copy link
Copy Markdown
Owner

Jikoo commented May 7, 2026

I appreciate the attempt to contribute a fix, but I hope you can see where I'm coming from. If I have to re-prompt through you, we might be here for weeks with communication delays. If I have to rewrite it myself, why would I not just do that?

The biggest problem with both of your iterations is a slightly subtle bug: they effectively undo the async part of the AsyncPlayerSpawnLocationEvent. Add in the extra player data read, and suddenly if anything it's going to have worse performance. Sure, you might not get warnings about the event being listened to, but that's really not super critical unless the event is actually scheduled to be removed, which it isn't.

The other problems are more me-problems: The AI does some weird things (like that abuse of an array for the location callback, ew), and it didn't make any effort to minimize the diff. It's hard to read and process. For a human author who would learn and grow as a developer, me taking the time to offer suggestions to fix that is an investment in the quality of the community. For an AI author, well, that's just what that model does, and I'm wasting my breath because the next person will be starting from a blank slate with it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants